package com.edu.app.service.impl.wechat;

import com.edu.app.exception.wechat.NotSupportHttpImpl;
import com.edu.app.exception.wechat.NotSupportStoreImpl;
import com.edu.app.model.wechat.*;
import com.edu.app.service.sys.wechat.WechatAccessTokenService;
import com.edu.app.util.http.HttpImplConfig;
import com.edu.app.util.http.HttpInterface;
import com.edu.app.util.http.HttpUtils;
import com.edu.app.util.wechat.WxTokenStorage;
import com.edu.app.util.wechat.WxTokenStoreUtil;


import java.io.IOException;
import java.util.concurrent.locks.Lock;


public  class WeChatAccessTokenServiceImpl implements WechatAccessTokenService {

    private HttpImplConfig httpImplConfig;
    private WechatConfig wechatConfig;
    /**
     * 获取access_token
     */
    String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";




    public WeChatAccessTokenServiceImpl(HttpImplConfig httpImplConfig, WechatConfig wechatConfig) {
        this.httpImplConfig = httpImplConfig;
        this.wechatConfig   = wechatConfig;
    }

    public WxTokenStorage getAccessTokenStorage() throws NotSupportStoreImpl {
        WxTokenStorage wxTokenStorage = WxTokenStoreUtil.GetWxStore(wechatConfig.getStoreImplName());
        return wxTokenStorage;
    }

    public String getAccessToken(boolean forceRefresh) throws NotSupportStoreImpl,WxErrorException {

            WxTokenStorage wxTokenStorage = getAccessTokenStorage();

            Lock lock = wxTokenStorage.getAccessTokenLock();
            try {
                lock.lock();
                if (wxTokenStorage.isAccessTokenExpired() || forceRefresh) {
                    String url = String.format(GET_ACCESS_TOKEN_URL,
                            wechatConfig.getAppid(),
                            wechatConfig.getAppsecret());

                    try {
                        HttpInterface httpInterface = HttpUtils.GetHttpInterface(httpImplConfig);
                        String response = httpInterface.HttpGetSync(url, null);

                        WxError error = WxError.fromJson(response, WxType.MP);
                        if (error.getErrcode() == 1) {
                            WxAccessToken accessToken = WxAccessToken.fromJson(response);
                            wxTokenStorage.updateAccessToken(accessToken.getAccess_token(),
                                    accessToken.getExpires_in());
                        }
                        else
                        {
                            throw new WxErrorException(error);
                        }

                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    } catch (NotSupportHttpImpl notSupportHttp) {
                        throw new RuntimeException(notSupportHttp);
                    }
                }
            } finally {
                lock.unlock();
            }
            return wxTokenStorage.getAccessToken();

    }

}
